# -*- coding: utf-8 -*-
"""
structure analysis based on lyric only by finding repetition

the basic problem : what is the structure of a lyric, from a larger scale view
or smaller view the result may be different
"""

from Lyric import Lyric

similarthres = 0.7
sadebug = False
sa1debug = False

"""
class LyricStruct:
    #result to store the lyric result
    #define the basic virtual class
    

    # have lyric and the split point
    pass
"""

def analysis(lyric):
    """
    renda version org
    input a lyric 
    output the lyricstruct
    """
    linelist = lyric.getlinelist()
    #print linelist
    slist = [[0,len(linelist)-1]]
    _ana1(linelist,slist)
    if sadebug:
        print "ana1"
        #printseg(linelist,slist)

    _ana2(linelist,slist)
    if sadebug:
        print "ana2"
        #printseg(linelist,slist)

    _ana3(linelist,slist)
    if sadebug:
        print "ana3"
        printseg(linelist,slist)
    
    _ana4(linelist,slist)
    #for the first line not similar but the last line similar

    return slist

def analysis1(lyric):
    """
    add another last sentense check _ana5
    """
    linelist = lyric.getlinelist()
    #print linelist
    slist = [[0,len(linelist)-1]]
    _ana1(linelist,slist)
    if sa1debug:
        print "ana1"
        printseg(linelist,slist)

    _ana2(linelist,slist)
    if sa1debug:
        print "ana2"
        printseg(linelist,slist)

    _ana3(linelist,slist)
    if sa1debug:
        print "ana3"
        printseg(linelist,slist)
    
    _ana4(linelist,slist)
    if sa1debug:
        print "ana4"
        printseg(linelist,slist)
    _ana5(linelist,slist)
    #for the first line not similar but the last line similar

    return slist

def analysis2(lyric):
    """
    add another last sentense check _ana5
    """
    linelist = lyric.getlinelist()
    #print linelist
    slist = [[0,len(linelist)-1]]
    _ana1(linelist,slist)
    if sa1debug:
        print "ana1"
        printseg(linelist,slist)

    _ana2_2(linelist,slist)
    if sa1debug:
        print "ana2"
        printseg(linelist,slist)

    _ana3_2(linelist,slist)
    if sa1debug:
        print "ana3"
        printseg(linelist,slist)
    
    _ana4(linelist,slist)
    if sa1debug:
        print "ana4"
        printseg(linelist,slist)
    _ana5(linelist,slist)
    #for the first line not similar but the last line similar

    return slist


def _senSimilar(s1,s2):
    if s1 == s2:
        return 1
    return 0

def _insertlist(l,index):
    """
    slist format is [[beg,end]]
    """
    #raise Exception("slist structure here")
    # list order is not right
    #raise Exception("the insert is not right, disorder the sequence of the seg")
    for i in range(len(l)):
        seg = l[i]
        if seg[0] < index and index <= seg[1]:
            tmpseg= []
            tmpseg.append(index)
            tmpseg.append(seg[1])
            l.insert(i+1,tmpseg)
            seg[1] = index-1
    #here should have some exception

def _ana1(linelist,slist):
    while True:
        orglen = len(slist)
        for seg in slist:
            #check the segment and insert into the seg
            for i in range(seg[0],seg[1]+1):
                # raise Exception
                #raise Exception('range of j error')
                for j in range(i+1,seg[1]+1):
                    if _senSimilar(linelist[i]['content'],linelist[j]['content']) > similarthres:
                        #print str(i)+":"+linelist[i]['content']
                        #print str(j)+":"+linelist[j]['content']
                        #print slist
                        _insertlist(slist,j)
                        #print slist

        if len(slist) == orglen:
            #no change
            break
        #print slist

def _ana2(linelist,slist):
    """
    check from back
    similar between seg
    todo:
    the last weizou part detection
    """
    while True:
        orglen = len(slist)
        found=False
        for i in range(len(slist)-1,0,-1):
            if i == len(slist)-1 and slist[i][1]-slist[i][0] + 1 < 3:
                #the last part
                continue
            for j in range(i-1,-1,-1):
                #check the similar sen in par i and par j
                slisti = slist[i]#the s part and the later part
                slistj = slist[j]
                if _senSimilar(linelist[slisti[0]]['content'],linelist[slistj[0]]['content'])>similarthres:
                    continue

                #output the segi and segj??
                for ii in range(slisti[0],slisti[1]+1):
                    for ji in range(slistj[0],slistj[1]+1):                
                        #the two for sequence???
                        #ji first
                        # how to break to the while level
                        if _senSimilar(linelist[ii]['content'],linelist[ji]['content'])>similarthres:
                            #print slist
                            #print ii
                            #print ji
                            _insertlist(slist,ji)
                            
                            if len(slist) != orglen:#insert may be not successful for collision
                                found =True
                        #here take wangfei-chuanqi for example, the last sentence problem

                        if found:
                            break
                    if found:
                        break
                if found:
                    break
            if found:
                break
        if len(slist) == orglen:
            #print str(i)+"i:j"+str(j)
            break

def _ana2_2(linelist,slist):
    """
    check from back,similar between seg
    check to solve the too detail problem
    """
    while True:
        orglen = len(slist)
        found=False
        for i in range(len(slist)-1,0,-1):
            if i == len(slist)-1 and slist[i][1]-slist[i][0] + 1 < 3:
                #the last part
                continue
            for j in range(i-1,-1,-1):
                #check the similar sen in par i and par j
                slisti = slist[i]#the s part and the later part
                slistj = slist[j]
                if _senSimilar(linelist[slisti[0]]['content'],linelist[slistj[0]]['content'])>similarthres:
                    continue

                #output the segi and segj??
                for ii in range(slisti[0],slisti[1]+1):
                    for ji in range(slistj[0],slistj[1]+1):                
                        #the two for sequence???
                        #ji first
                        # how to break to the while level
                        if _senSimilar(linelist[ii]['content'],linelist[ji]['content'])>similarthres:
                            #raise Exception("check the sentence above")
                            if ii != 0 and ji != 0:
                                if _senSimilar(linelist[ii-1]['content'],linelist[ji-1]['content']) > similarthres:
                                    continue

                            #print slist
                            #print ii
                            #print ji
                            _insertlist(slist,ji)
                            
                            if len(slist) != orglen:#insert may be not successful for collision
                                found =True
                        #here take wangfei-chuanqi for example, the last sentence problem

                        if found:
                            break
                    if found:
                        break
                if found:
                    break
            if found:
                break
        if len(slist) == orglen:
            #print str(i)+"i:j"+str(j)
            break


def _ana3(linelist,slist):
    """
    check from front
    similar between seg
    """
    while True:
        orglen = len(slist)
        found = False
        for i in range(len(slist)-1):
            if i == len(slist)-1 and slist[i][1]-slist[i][0] + 1 < 3:
                #the last part
                continue
            for j in range(i+1,len(slist)):
                #check the similar sen in par i and par j
                slisti = slist[i]
                slistj = slist[j]
                #first similar
                if _senSimilar(linelist[slisti[0]]['content'],linelist[slistj[0]]['content'])>similarthres:
                    continue               

                for ii in range(slisti[0],slisti[1]+1):
                    for ji in range(slistj[0],slistj[1]+1):
                        # how to break to the while level
                        if _senSimilar(linelist[ii]['content'],linelist[ji]['content'])>similarthres:
                            if sadebug:
                                print slist
                                print ii
                                print ji
                            _insertlist(slist,ji)
                            #here should break , or the split is too deep for
                            #the paragraph is the same on each sentense
                            if len(slist) != orglen:
                                found = True
                            # it's not that simple here
                        if found:
                            break
                    if found:
                        break
                if found:
                    break
            if found:
                break

        if len(slist) == orglen:
            break

def _ana3_2(linelist,slist):
    """
    check from front,similar between seg
    """
    while True:
        orglen = len(slist)
        found = False
        for i in range(len(slist)-1):
            if i == len(slist)-1 and slist[i][1]-slist[i][0] + 1 < 3:
                #the last part
                continue
            for j in range(i+1,len(slist)):
                #check the similar sen in par i and par j
                slisti = slist[i]
                slistj = slist[j]
                #first similar
                if _senSimilar(linelist[slisti[0]]['content'],linelist[slistj[0]]['content'])>similarthres:
                    continue               

                for ii in range(slisti[0],slisti[1]+1):
                    for ji in range(slistj[0],slistj[1]+1):
                        # how to break to the while level
                        if _senSimilar(linelist[ii]['content'],linelist[ji]['content'])>similarthres:
                            #raise Exception("check sentense above")
                            if ii != 0 and ji != 0:
                                if _senSimilar(linelist[ii-1]['content'],linelist[ji-1]['content']) > similarthres:
                                    continue

                            _insertlist(slist,ji)
                            #here should break , or the split is too deep for
                            #the paragraph is the same on each sentense
                            if len(slist) != orglen:
                                found = True
                            # it's not that simple here
                        if found:
                            break
                    if found:
                        break
                if found:
                    break
            if found:
                break

        if len(slist) == orglen:
            break



def _ana4(linelist,slist):
    """
    check the similarity of the last sentense    
    """
    while True:
        orglen = len(slist)
        found = False
        for i in range(len(slist)-1,0,-1):
            if i == len(slist)-1 and slist[i][1]-slist[i][0] + 1 < 3:
                #the last part
                continue
            for j in range(i-1,-1,-1):
                #check the similar sen in par i and par j
                slisti = slist[i]
                slistj = slist[j]

                #first similar
                #why check the first sentense???
                if _senSimilar(linelist[slisti[0]]['content'],linelist[slistj[0]]['content'])>similarthres:
                    continue               
                lastseni = linelist[slisti[1]]['content']
                for ji in range(slistj[0],slistj[1]+1):
                    if _senSimilar(linelist[ji]['content'],lastseni) > similarthres:
                        _insertlist(slist,ji+1)
                        if len(slist) != orglen:
                            found = True
                        if found:
                            break
                    if found:
                        break
                """
                #from wangfei chuanqi lastsenj is also needed
                lastsenj = linelist[slistj[1]]['content']
                for ii in range(slisti[0],slisti[1]+1):
                    if _senSimilar(linelist[ii]['content'],lastsenj) > similarthres:
                        __insertlist(slist,ii+1)
                        found = True
                        if found:
                            break
                if found:
                    break
                """
            if found:
                break

        if len(slist) == orglen:
            break

def _ana5(linelist,slist):
    """
    check the similarity of the last sentense    
    """
    while True:
        orglen = len(slist)
        found = False
        for i in range(len(slist)-1,0,-1):
            if i == len(slist)-1 and slist[i][1]-slist[i][0] + 1 < 3:
                #the last part
                continue
            for j in range(i-1,-1,-1):
                #check the similar sen in par i and par j
                slisti = slist[i]
                slistj = slist[j]

                lastseni = linelist[slisti[1]]['content']
                #print str(i)+lastseni

                for ji in range(slistj[0],slistj[1]):#skip the last sentence
                    if _senSimilar(linelist[ji]['content'],lastseni) > similarthres:
                        _insertlist(slist,ji+1)
                        #here should check the insert 
                        if len(slist) != orglen:
                            found = True
                        if found:
                            break
                    if found:
                        break
                """
                #from wangfei chuanqi lastsenj is also needed
                lastsenj = linelist[slistj[1]]['content']
                for ii in range(slisti[0],slisti[1]+1):
                    if _senSimilar(linelist[ii]['content'],lastsenj) > similarthres:
                        __insertlist(slist,ii+1)
                        found = True
                        if found:
                            break
                if found:
                    break
                """
            if found:
                break

        if len(slist) == orglen:
            break


def printseg(linelist,segs):
    """
    debug function
    """
    for i in range(len(segs)):
        seg = segs[i]
        print "seg"+str(i)
        for i in range(seg[0],seg[1]+1):
            print str(linelist[i]['time'])+":"+linelist[i]['content']

if __name__ == "__main__":
    l = Lyric()
    #fname = "harrybobo.lrc"
    #fname = "wangfei.txt"
    fname = "she-toodetail.lrc"
    l.loadfile(fname)
    linelist = l.getlinelist()

    for line in linelist:
        #print str(line['time'])+":"+line['content']
        a = 1

    segs = analysis1(l)
    #printseg(linelist,segs)
